#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

from common.common import execute_cmd, execute_cmd_with_input, get_win_dir
from exchange.commons.command import Commands

# powershell路径
PS_LOC = f"{get_win_dir()}/system32/WindowsPowerShell/v1.0/powershell.exe"
# 执行命令超时时间，120s
TIMEOUT = 120
DEFAULT_DEPTH = 10


def execute_without_auth(script):
    '''
    执行powershell脚本，无认证方式
    :param script: 执行的脚本
    :return: 脚本输出，与原来的ps1脚本输出格式一致
    '''
    # 直接执行脚本命令
    code, out, err = execute_cmd([PS_LOC, script], timeout=TIMEOUT, cmd_array_flag=True)
    result = {"ReturnCode": code}
    if err is None or len(err) == 0:
        # 输出的倒数第二个是命令执行的输出
        result["Output"] = out
    else:
        result["ReturnCode"] = code if code != "0" else "-1"
        result["Output"] = err
    return result


def execute_with_depth(username, password, script, depth, session_name="session"):
    '''
    执行powershell脚本，返回值为脚本输出
    :param username: 用户名
    :param password: 密码
    :param script: 执行的脚本
    :param session_name: 创建的session名称
    :param depth: json深度
    :return: 脚本输出，与原来的ps1脚本输出格式一致
    '''
    # 获取主机名称
    code, hostname, err = execute_cmd([PS_LOC, "hostname"], timeout=TIMEOUT, cmd_array_flag=True)
    hostname = hostname.strip()
    # 拼接命令
    cmd = Commands.OPERATION_SCRIPT.format(session_name=session_name, hostname=hostname, username=username,
                                           password=password, cmd=script, depth=depth)
    # 执行命令
    code, out, err = execute_cmd_with_input([PS_LOC, cmd], timeout=TIMEOUT, cmd_array_flag=True)
    result = {"ReturnCode": code}
    if err is None or len(err) == 0:
        # 过滤掉空行
        out_list = list(filter(lambda x: len(x.strip()) > 0, out.splitlines()))
        # 去除每行返回值前后的空格
        out_list = list(map(lambda x: x.strip(), out_list))
        # 输出的倒数第二个或者out_list只有一条数据是命令执行的输出，如果命令无输出，返回空列表
        if out_list is None or len(out_list) == 0:
            result["Output"] = "[]"
        elif len(out_list) == 1:
            result["Output"] = out_list[-1] if not out_list[-1].startswith("PS ") else "[]"
        else:
            result["Output"] = out_list[-2] if not out_list[-2].startswith("PS ") else "[]"
    else:
        result["ReturnCode"] = code if code != "0" else "-1"
        result["Output"] = err
    return result


def execute_without_timeout(username, password, script, session_name="session"):
    '''
    执行powershell脚本，返回值为脚本输出
    :param username: 用户名
    :param password: 密码
    :param script: 执行的脚本
    :param session_name: 创建的session名称
    :return: 脚本输出，与原来的ps1脚本输出格式一致
    '''
    # 获取主机名称
    code, hostname, err = execute_cmd([PS_LOC, "hostname"], timeout=TIMEOUT, cmd_array_flag=True)
    hostname = hostname.strip()
    # 拼接命令
    cmd = Commands.OPERATION_SCRIPT.format(session_name=session_name, hostname=hostname, username=username,
                                           password=password, cmd=script, depth=DEFAULT_DEPTH)
    # 执行命令
    code, out, err = execute_cmd_with_input([PS_LOC, cmd], timeout=None, cmd_array_flag=True)
    result = {"ReturnCode": code}
    if err is None or len(err) == 0:
        # 过滤掉空行
        out_list = list(filter(lambda x: len(x.strip()) > 0, out.splitlines()))
        # 去除每行返回值前后的空格
        out_list = list(map(lambda x: x.strip(), out_list))
        # 输出的倒数第二个或者out_list只有一条数据是命令执行的输出，如果命令无输出，返回空列表
        if out_list is None or len(out_list) == 0:
            result["Output"] = "[]"
        elif len(out_list) == 1:
            result["Output"] = out_list[-1] if not out_list[-1].startswith("PS ") else "[]"
        else:
            result["Output"] = out_list[-2] if not out_list[-2].startswith("PS ") else "[]"
    else:
        result["ReturnCode"] = code if code != "0" else "-1"
        result["Output"] = err
    return result


def execute(username, password, script, session_name="session"):
    '''
    执行powershell脚本，返回值为脚本输出
    :param username: 用户名
    :param password: 密码
    :param script: 执行的脚本
    :param session_name: 创建的session名称
    :return: 脚本输出，与原来的ps1脚本输出格式一致
    '''
    # 获取主机名称
    code, hostname, err = execute_cmd([PS_LOC, "hostname"], timeout=TIMEOUT, cmd_array_flag=True)
    hostname = hostname.strip()
    # 拼接命令
    cmd = Commands.OPERATION_SCRIPT.format(session_name=session_name, hostname=hostname, username=username,
                                           password=password, cmd=script, depth=DEFAULT_DEPTH)
    # 执行命令
    code, out, err = execute_cmd_with_input([PS_LOC, cmd], timeout=TIMEOUT, cmd_array_flag=True)
    result = {"ReturnCode": code}
    if err is None or len(err) == 0:
        # 过滤掉空行
        out_list = list(filter(lambda x: len(x.strip()) > 0, out.splitlines()))
        # 去除每行返回值前后的空格
        out_list = list(map(lambda x: x.strip(), out_list))
        # 输出的倒数第二个或者out_list只有一条数据是命令执行的输出，如果命令无输出，返回空列表
        if out_list is None or len(out_list) == 0:
            result["Output"] = "[]"
        elif len(out_list) == 1:
            result["Output"] = out_list[-1] if not out_list[-1].startswith("PS ") else "[]"
        else:
            result["Output"] = out_list[-2] if not out_list[-2].startswith("PS ") else "[]"
    else:
        result["ReturnCode"] = code if code != "0" else "-1"
        result["Output"] = err
    return result


def execute_with_utf8(username, password, script, session_name="session"):
    '''
    执行powershell脚本，返回值为脚本输出
    :param username: 用户名
    :param password: 密码
    :param script: 执行的脚本
    :param session_name: 创建的session名称
    :return: 脚本输出，与原来的ps1脚本输出格式一致
    '''
    # 获取主机名称
    code, hostname, err = execute_cmd([PS_LOC, "hostname"], timeout=TIMEOUT, cmd_array_flag=True)
    hostname = hostname.strip()
    # 拼接命令
    cmd = Commands.OPERATION_SCRIPT.format(session_name=session_name, hostname=hostname, username=username,
                                           password=password, cmd=script, depth=DEFAULT_DEPTH)
    # 执行命令
    code, out, err = execute_cmd_with_input([PS_LOC, cmd], timeout=TIMEOUT, cmd_array_flag=True, is_force_utf8=True)
    result = {"ReturnCode": code}
    if err is None or len(err) == 0:
        # 过滤掉空行
        out_list = list(filter(lambda x: len(x.strip()) > 0, out.splitlines()))
        # 过滤掉utf8的回显
        if len(out_list) > 0 and "65001" in out_list[0]:
            out_list = out_list[1:]
        # 去除每行返回值前后的空格
        out_list = list(map(lambda x: x.strip(), out_list))
        # 输出的倒数第二个或者out_list只有一条数据是命令执行的输出，如果命令无输出，返回空列表
        if out_list is None or len(out_list) == 0:
            result["Output"] = "[]"
        elif len(out_list) == 1:
            result["Output"] = out_list[-1] if not out_list[-1].startswith("PS ") else "[]"
        else:
            result["Output"] = out_list[-2] if not out_list[-2].startswith("PS ") else "[]"
    else:
        result["ReturnCode"] = code if code != "0" else "-1"
        result["Output"] = err
    return result


def get_hostname():
    '''
    执行powershell脚本，获取hostname
    '''
    # 获取主机名称
    code, hostname, err = execute_cmd([PS_LOC, "hostname"], timeout=TIMEOUT, cmd_array_flag=True)
    hostname = hostname.strip()
    result = {"ReturnCode": code}
    if err is None or len(err) == 0:
        result["Output"] = hostname
    else:
        result["ReturnCode"] = code if code != "0" else "-1"
        result["Output"] = err
    return result


def execute_with_output_bool(username, password, script, session_name="session"):
    '''
    执行powershell脚本，返回值为True or False
    :param username: 用户名
    :param password: 密码
    :param script: 执行的脚本
    :param session_name: 创建的session名称
    :return: True or False
    '''
    # 获取主机名称
    code, hostname, err = execute_cmd([PS_LOC, "hostname"], timeout=TIMEOUT, cmd_array_flag=True)
    hostname = hostname.strip()
    # 拼接命令
    cmd = Commands.OPERATION_SCRIPT_OUT_NULL.format(session_name=session_name, hostname=hostname, username=username,
                                                    password=password, cmd=script)
    # 执行命令
    code, out, err = execute_cmd_with_input([PS_LOC, cmd], timeout=TIMEOUT, cmd_array_flag=True)
    result = {"ReturnCode": code}
    if err is None or len(err) == 0:
        # 过滤掉空行
        out_list = list(filter(lambda x: len(x.strip()) > 0, out.splitlines()))
        # 去除每行返回值前后的空格
        out_list = list(map(lambda x: x.strip(), out_list))
        # 输出的倒数第二个或者out_list只有一条数据是命令执行的输出，如果命令无输出，返回空列表
        if out_list is None or len(out_list) == 0:
            result["Output"] = "[]"
        elif len(out_list) == 1:
            result["Output"] = out_list[-1]
        else:
            result["Output"] = out_list[-2]
    else:
        result["ReturnCode"] = code if code != "0" else "-1"
        result["Output"] = err
    return result
